
promise 是 ES6 新增的語法,主要用來處理非同步行為,promise 也可以直接用中文理解:這個承諾可以被兌現或是拒絕,也就對應到了 resolve(成功) 以及 reject(失敗)。
透過建構函式 new 一波,一旦建立後就有相關的方法可以呼叫(then、catch 等)。
const promise = new Promise((resolve, reject) => {
resolve("success");
reject("error");
});
而 Promise 內必須傳入一個函式,這個函式會接收兩個參數,分別是 resolve & reject(選填),成功及失敗時會被調用,一旦調用後 promise 的狀態就會被改變,同時只能調用其中一種。
上面提到調用後狀態就會被改變,狀態可以分為以下:
pending 承諾尚未兌現 (PromiseState:Pending)resolved 承諾已履行 (PromiseState:Fulfilled)rejected 拒絕承諾 (PromiseState:Rejected)要注意的是,一旦狀態被改變後就不會再更動了。我們可以 log 出 PromiseState 來看看現在的狀態:
const promise = new Promise((resolve, reject) => {
// ...
});
console.log(promise)

一般在使用 promise 會用 then 和 catch 代表成功及失敗要做的事情:
promise.then(); // Promise 回傳正確
promise.catch(); // Promise 回傳失敗
promise.finally(); // 非同步執行完畢(無論是否正確完成)
在 then 中使用 return 回傳另一個 promise,就是 Promise 鏈的用法,再下一個 then 中會繼續執行,就不會有 callback hell 的情況發生。
promise
.then((res) => {
console.log(res)
return promise; // 回傳 promise
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
但如果第二個 promise 被拒絕則會接跳到 catch 的地方。
另外 finally() 非同步執行完畢後才會執行,可以用來確認該 promise 是否有執行。
接下來看看 Promise 還有哪些方法可以使用:
當我們想要一次執行多個 promise 就可以使用 all(),參數中接受陣列,陣列中放多個 promise。
用法與一般的類似,實際寫會類似這樣:
// n < 3 才會成立
function promise(n) {
return new Promise((resolve, reject) => {
if (n < 3) {
resolve("success");
} else {
reject("error");
}
});
}
// 參數放陣列,這邊都成功所以不會進到 catch
Promise.all([promise(1), promise(2)])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
all() 的注意點:
promise 完成後會回傳一個陣列,陣列裝著各個 promise 的 callback。rejected,則回傳第一個 rejected 的 promise。與上面的 all() 差不多,參數一樣接受陣列,差別在於:
只要任一個 promise 狀態改變,則回傳該個 promise 的 callback。
Promise.resolve() 函數用來將一個物件轉型為 Promise (如果它不是一個 Promise 物件),然後立刻 resolve 它。
const promise = Promise.resolve("success");
promise.then((res) => {
console.log(res); // success
});
Promise.reject() 函數用來將一個物件轉型為 Promise (如果它不是一個 Promise 物件),然後立刻 reject 它。
簡單來說就是跟上面相反
const promise = Promise.reject("error");
promise.catch((err) => {
console.log(err); // error
});
Async Await 是 ES7 新增的語法,也同樣用來處理非同步行為、並且是 Pormise 的語法糖,能讓函式以「同步」的方式來執行程式。
語法上有兩個重點:
function 前面添加 async 關鍵字。try & catch 做例外處理。// 建立一個 promise
const promise = new Promise((resolve, reject) => {
resolve(1)
});
// 立即執行這個 async function
(async function asyncFn(){
try {
const res = await promise;
console.log(res) // 印出 1
}catch(err){
console.log(err)
}
})()
上面的範例中可以看到 await,這個用法等同於 promise 中使用的 then。這個 API 與 async 是好朋友,並不會單獨出現,也就是外層如果沒有 async 關鍵字,內部無法使用 await。
當然 await 沒有規定執行次數:
const promise = (number) => {
return new Promise((resolve, reject) => {
resolve(number)
})
}
(async function asyncFn(){
try {
const res = await promise(1);
const res2 = await promise(2);
}catch(err){
console.log(err)
}
})()
Promise 中使用 catch 來捕捉錯誤,在 async function 如果沒有特別針對錯誤做處理的話,一旦發生錯誤會導致程式碼無法繼續執行。
// 參數 number 大於 10,進入 reject
const promise = (number) => {
return new Promise((resolve, reject) => {
if(number > 10){
reject("WTF!!!!")
}else{
resolve(number)
}
})
}
(async function asyncFn(){
try {
// 進入 rejected 狀態,前往 catch
const res = await promise(99);
}catch(err){
console.log(err) // 印出 WTF!!!!
}
})()